﻿using UnityEngine;
using UnityEngine.UI;
namespace GX
{
    public abstract class BasePanel
    {
        /**
        * bit[0,1] 可视状态：0不可见，1可见但不是active（非top的），2可见并且active(top)
        */
        public const int Mask_Visible = 0x03;//0011
        /**
        *  bit[2,3] 生命周期（加载/创建/销毁）状态：0为加载none，1加载中loading， 2 加载完loadDone 3：创建created
        */
        public const int Mask_Load = 0x0c;//1100

        public const int Status_InVisible = 0;
        public const int Status_Visible = 1;

        public const int Load_Status_None = 0;
        public const int Load_Status_Loading = 1;
        public const int Load_Status_Loaded = 2;
        public const int Load_Status_Create = 3;


        int _flag;
        int _sortOrder = -1;

        internal UIManagerService mgr { get; private set; }
        public string name { get; private set; }
        virtual public int layer { get { return 0; } }
        public bool isLoading { get { return GetLoadtatus() == UIManagerService.Load_Status_Loading; } }
        public bool isLoaded { get { return GetLoadtatus() >= UIManagerService.Load_Status_Loaded; } }
        public bool isCreated { get { return GetLoadtatus() == UIManagerService.Load_Status_Create; } }
        public bool isOpen { get { return GetVisibleStatus() >= UIManagerService.Status_Visible; } }
        public bool isActive { get { return mgr.IsTop(name); } }

        internal void Initialize(UIManagerService mgr, string name)
        {
            this.mgr = mgr;
            this.name = name;
        }
        internal void SetVisibleStatus(int value)
        {
            BitHelper.WriteMask(ref _flag, value, Mask_Visible);
            SetVisible(this.isOpen);
        }
        abstract public void SetVisible(bool v);
        internal int GetVisibleStatus()
        {
            return _flag & Mask_Visible;
        }
        internal void SetLoadStatus(int value)
        {
            BitHelper.WriteMask(ref _flag, value << 2, Mask_Load);
        }
        internal int GetLoadtatus()
        {
            return (_flag & Mask_Load) >> 2;
        }
        internal void TryCreate()
        {
            int loadStatus = GetLoadtatus();
            if (loadStatus == UIManagerService.Load_Status_Create)
                return;
            if (loadStatus == UIManagerService.Load_Status_Loaded)
            {
                FinishLoad();
            }
            else if (loadStatus == UIManagerService.Load_Status_None)
            {
                SetLoadStatus(UIManagerService.Load_Status_Loading);
                StartLoad();
            }
        }
        virtual protected void StartLoad()
        {
        }
        protected void FinishLoad()
        {
            int loadStatus = GetLoadtatus();
            if (loadStatus == UIManagerService.Load_Status_Loading)
            {
                SetLoadStatus(UIManagerService.Load_Status_Loaded);
                if (!isOpen)
                    return;
            }
            loadStatus = GetLoadtatus();
            bool isVisible = this.isOpen;
            if (loadStatus == UIManagerService.Load_Status_Loaded)
            {
                if (isVisible && CreateUI())
                {
                    SetLoadStatus(UIManagerService.Load_Status_Create);
                }
            }
            loadStatus = GetLoadtatus();
            if (isVisible && null != mgr && loadStatus == UIManagerService.Load_Status_Create)
            {
                mgr.OnLoaded(this);
            }
        }

        abstract protected bool CreateUI();
        internal void OnEnterInternal(Event args)
        {
            if (this.isCreated)
                this.OnEnter(args);
        }
        virtual protected void OnEnter(Event args) { }
        internal void OnResumeInternal()
        {
            if (this.isCreated)
                this.OnResume();
        }
        virtual protected void OnResume() { }
        internal void OnPauseInternal()
        {
            if (this.isCreated)
                this.OnPause();
        }
        virtual protected void OnPause() { }
        internal void OnExitInternal()
        {
            if (this.isCreated)
                this.OnExit();
        }
        virtual protected void OnExit() { }
        internal void OnDestroyInternal()
        {
            if (this.isCreated)
            {
                this.OnDestroy();
            }
        }
        virtual protected void OnDestroy() { }
        public int sortOrder
        {
            get { return _sortOrder; }
            internal set
            {
                _sortOrder = value;
                if (this.isCreated)
                {
                    UpdateOrder();
                }

            }
        }
        abstract protected void UpdateOrder();
    }
}